--[[ Last modification: 2020/3/18 Ammunition wheel (by Tronex) Suppressor toggle keybind (by TKGP) Modified by Tronex Suppressor Toggle can be binded from keybinds in options 2018/9/2 - Removed actor_on_update callback, the script relies on a timer instead. No need to run check at all times Scopes support (by Darryl123) --]] local string_find = string.find local string_gsub = string.gsub ------------------------------- -- SCOPES ------------------------------- local scopes_table = utils_data.collect_sections(ini_sys, {"addons_table"}) local function transfer_item(id) local item = level.object_by_id(id) if not (item) then return false end db.actor:transfer_item(item, db.actor) return true end local function check_scope(addon_sect, weapon_sect) local valid_addons = parse_list(ini_sys, weapon_sect, "scopes") for k, v in pairs(valid_addons) do if (v == addon_sect) then return true end end return false end function get_weapon_slot() local slot = db.actor:active_slot() local item if (slot == 1 or slot == 2 or slot == 3) then item = db.actor:item_in_slot(slot) if (item and IsWeapon(item)) then return item end end item = db.actor:item_in_slot(1) if (item and IsWeapon(item)) then return item end item = db.actor:item_in_slot(2) if (item and IsWeapon(item)) then return item end item = db.actor:item_in_slot(3) if (item and IsWeapon(item)) then return item end end function attach_scope(item, weapon) -- Return if the addon or weapon aren't valid. if not (item and weapon) then return end -- An addon has already been attached or none can be used. local parent_section = ini_sys:r_string_ex(weapon:section(),"parent_section") if (not parent_section or weapon:section() ~= parent_section) then return end -- Modified weapon does not exist and as such can't be used. local child_section = (parent_section .. "_" .. item:section()) if not (ini_sys:section_exist(child_section)) then return end -- Determine whether the addon is valid for the weapon selected. if not (check_scope(item:section(), weapon:section())) then return end -- Create objects for the 'before' and 'after' attachment weapons. local old_weapon = alife_object(weapon:id()) local new_weapon = old_weapon and alife_clone_weapon(old_weapon, child_section) if new_weapon then alife_release(item) end end function detach_scope(weapon) -- Return if the weapon is not valid. if not (weapon) then return end -- An addon has not been attached or none can be detached. local parent_section = ini_sys:r_string_ex(weapon:section(),"parent_section") if (not parent_section or weapon:section() == parent_section) then return end -- Get weapon owner local old_weapon = alife_object(weapon:id()) local owner = old_weapon and old_weapon.parent_id and get_object_by_id(old_weapon.parent_id) if (not owner) then printf("~ item_weapon.detach_scope | weapon owner not found") return end -- Determine which addon is attached to the weapon. -- Create the item in the actor's inventory when found. for k, v in pairs(scopes_table) do if (string.find(weapon:section(), k)) then --give_object_to_actor(k) alife_create_item(k, owner) break end end -- Create objects for the 'before' and 'after' detachment weapons. local new_weapon = old_weapon and alife_clone_weapon(old_weapon, parent_section) end function menu_scope(weapon) -- Return if the weapon is invalid. if (not weapon) then return end -- Return if the weapon has no parent section. local parent_section = ini_sys:r_string_ex(weapon:section(),"parent_section") if (not parent_section or weapon:section() == parent_section) then return end --[[ Return if the weapon is not in the actor's inventory. local p = weapon:parent() if not (p and p:id() == AC_ID) then return end --]] -- Return the context option to detach an addon. return game.translate_string("st_detach_scope") end function menu_scope_inv(weapon) -- Return if LUA inventory is enabled, detach scope menu is already included there if ui_inventory.is_enabled() then return end return menu_scope(weapon) end function func_scope(weapon) detach_scope(weapon) end ------------------------------- -- SILENCER ------------------------------- local sil_delay = 1500 -- Additional time (milliseconds) before weapon is reequipped local SIL_ATTACH_SOUND = "interface\\inv_attach_addon" local SIL_DETACH_SOUND = "interface\\inv_detach_addon" local sil_info, sil_attach, sil_sound, sil_restore function test_silencer() if db.actor and not sil_info then local weapon = db.actor:active_item() if weapon and weapon:weapon_silencer_status() == 2 then local supSection = utils_item.get_param(weapon:section(), weapon:id(), "silencer_name", "string") local proceed = false if weapon:weapon_is_silencer() then -- if active weapon has silencer proceed = true sil_attach = false elseif db.actor:object(supSection) then -- if active weapon doesn't have silencer and silencer is in inv proceed = true sil_attach = true end if proceed then db.actor:hide_weapon() sil_info = {id = weapon:id(), section = supSection} CreateTimeEvent(0,"delay_silencer",1,toggle_silencer) end end end end function toggle_silencer() if sil_restore then sil_restore = false db.actor:restore_weapon() RemoveTimeEvent(0,"delay_silencer") end if sil_info and not db.actor:active_item() then local success = false local weapon = level.object_by_id(sil_info.id) if weapon and weapon:parent() and weapon:parent():id() == AC_ID then local newSound if sil_attach then -- if attach the silencer local suppressor = db.actor:object(sil_info.section) if suppressor then weapon:weapon_addon_attach(suppressor) newSound = SIL_ATTACH_SOUND success = true end else -- if de-attach the silencer weapon:weapon_addon_detach(sil_info.section, true) newSound = SIL_DETACH_SOUND success = true end if newSound then if sil_sound then sil_sound:stop() end sil_sound = sound_object(newSound) sil_sound.volume = 1 sil_sound:play(db.actor, 0, sound_object.s2d) end end sil_info = nil if success then sil_restore = true ResetTimeEvent(0,"delay_silencer",(sil_delay/1000)) else --restore = true db.actor:restore_weapon() RemoveTimeEvent(0,"delay_silencer") end end end ------------------------------- -- AMMO ------------------------------- _G._NO_DAMAGED_AMMO = true -- if you want to get verybad ammo, set this to false local ui_delay = 0 -- small hack to prevent instant keybind action (between switching to next ammo type, and start the wheel again) local ui_delay_const = 200 -- [ms] local cache_ammo = {} local nums_dik = {} function relocate_ammo_to_actor(actor, npc, section, amount) if not (actor and section and amount and IsItem("ammo",section)) then return end alife_create_item(section, actor, {ammo = amount}) news_manager.relocate_item(actor, "in", section, amount) end function relocate_ammo_from_actor(actor, npc, section, amount) if not (actor and amount) then return end if (npc == nil) then --printe("!ERROR: Couldn't relocate_item_from_actor | no npc found!") end local box_size = IsItem("ammo",section) if (not box_size) then return end local cnt = amount local keep_itr = true actor:iterate_inventory( function(temp, obj) --printf("~relocate_item_from_actor | checked [%s]", obj:section()) if keep_itr and (obj and obj:section() == section) then --printf("-relocate_item_from_actor | found needed section [%s]", section) cnt = cnt - obj:ammo_get_count() if (cnt >= 0) then if npc then actor:transfer_item(obj, npc) else alife_release(obj) end if (cnt == 0) then keep_itr = false end else local remain_1 = -cnt local remain_2 = obj:ammo_get_count() + cnt alife_process_item(section, obj:id(), {ammo = remain_1}) if npc then alife_create_item(section, npc, {ammo = remain_2}) end keep_itr = false end end end) if cnt > 0 then printe("! ERROR: Couldn't relocate_item_from_actor | not enough item [%s] recolated! need %s more", section, cnt) end news_manager.relocate_item(actor, "out", section, amount) end function ammo_aggregation(obj, npc) -- Sort ammo boxes (called from game_setup) if (not npc) then npc = db.actor end local is_box = IsInvbox(npc) local section = obj:section() local size = obj:ammo_get_count() local box_size = obj:ammo_box_size() -- Replace damaged ammo with old if _NO_DAMAGED_AMMO and string_find(section,"verybad") then local new_section = string_gsub(section,"verybad","bad") if ini_sys:section_exist(new_section) then alife_release(obj) alife_create_item(new_section, npc, {ammo = size}) --printf("~ replaced [%s] with [%s]", section, new_section) return true end end -- Replace home-made buck ammo with regular type if (section == "ammo_12x70_buck_self") then local new_section = "ammo_12x70_buck" if ini_sys:section_exist(new_section) then alife_release(obj) alife_create_item(new_section, npc, {ammo = size}) --printf("~ replaced [%s] with [%s]", section, new_section) return true end end if (size == box_size) then return true end local ammos = {} -- collect ammos except this one; we use it for remainder function collect(temp, item) if (section == item:section() and item:id() ~= obj:id() and item:ammo_get_count() < box_size) then ammos[#ammos+1] = item:id() size = size + item:ammo_get_count() end end if is_box then npc:iterate_inventory_box(collect) else npc:iterate_inventory(collect) end -- didn't find any others if (size == obj:ammo_get_count()) then return true end local fill = math.floor(size/box_size) local remainder = size - (box_size*fill) if (remainder > 0) then obj:ammo_set_count(remainder) else ammos[#ammos+1] = obj:id() end for i=1,#ammos do local item = level.object_by_id(ammos[i]) if (item) then if (fill > 0) then item:ammo_set_count(box_size) fill = fill - 1 else if not is_box then npc:drop_item(item) end alife_release_id(ammos[i]) end end end return true end function ammo_aggregation_full(npc_id) local npc = npc_id and db.storage[npc_id] and db.storage[npc_id].object or level.object_by_id(npc_id) if (not npc) then return true end -- Ammo aggregation local ammo_sec_list = {} local function itr_ammo(npc,itm) local sec = itm:section() if IsItem("ammo",sec) and (not ammo_sec_list[sec]) then ammo_sec_list[sec] = true end end npc:iterate_inventory(itr_ammo,npc) for sec,_ in pairs(ammo_sec_list) do local obj = npc:object(sec) if obj then ammo_aggregation(obj, npc) end end return true end function ammo_injection(obj_1, obj_2, sec_1, sec_2) -- Gather weapon's ammo list local ammo_list = utils_item.get_ammo(obj_2:section(), obj_2:id(), true) if (not ammo_list[sec_1]) then return end -- Gather ammo box count and full size local ammo_list_n = utils_item.get_ammo(obj_2:section(), obj_2:id()) local ammo_count = obj_1:ammo_get_count() --local ammo_box_size = obj_1:ammo_box_size() -- Gather weapon info local wpn_ammo_type = obj_2:get_ammo_type() local wpn_ammo_sec = ammo_list_n[wpn_ammo_type + 1] local wpn_ammo_elapsed = obj_2:get_ammo_in_magazine() local wpn_ammo_mag_size = ini_sys:r_u32(sec_2, "ammo_mag_size") local wpn_one_shot = (ini_sys:r_string_ex(sec_2, "tri_state_reload") == "on") or (ini_sys:r_string_ex(sec_2, "class") == "WP_BM16") -- If the ammo type is different from new ammo box -> throw weapon's ammo in inventory + change weapon's ammo type local is_ammo_same = (wpn_ammo_sec == sec_1) if (not is_ammo_same) then if (wpn_ammo_elapsed > 0) then alife_create_item(wpn_ammo_sec, db.actor, { ammo = wpn_ammo_elapsed }) obj_2:unload_magazine() wpn_ammo_elapsed = 0 end for i=1,#ammo_list_n do if (ammo_list_n[i] == sec_1) then local wpn_ammo_new_type = (i - 1) obj_2:set_ammo_type(wpn_ammo_new_type) break end end end local ammo_to_wpn = wpn_ammo_mag_size - wpn_ammo_elapsed if (wpn_one_shot) then ammo_to_wpn = clamp(ammo_to_wpn,0,1) end local ammo_from_box = clamp(ammo_to_wpn,0,ammo_count) if (ammo_from_box > 0) then -- Adjust ammo box size that got taken from if (ammo_count > ammo_from_box) then obj_1:ammo_set_count(ammo_count - ammo_from_box) else alife_release_id(obj_1:id()) end -- Set the ammo size added to weapon obj_2:set_ammo_elapsed(wpn_ammo_elapsed + ammo_from_box) local prev_state = obj_2:get_state() -- Play reload effect if wpn_one_shot then xr_sound.set_sound_play(AC_ID,"reload_shell") level.add_cam_effector("camera_effects\\switch\\low" .. math.random(1,4) .. ".anm", 23239, false,'') else actor_effects.play_item_fx("reload_weapon_fast") local snd_reload = ini_sys:r_string_ex(sec_2,"snd_reload") utils_obj.play_sound(snd_reload) end end end function unload_all_weapons() db.actor:iterate_ruck( function(temp,obj) if IsWeapon(obj) and (not IsItem("fake_ammo_wpn",obj:section())) then obj:force_unload_magazine(true) end end) end function clear_cache(obj) if obj then cache_ammo[obj:id()] = nil else empty_table(cache_ammo) end end function remove_extra_ammo(npc_id) local se_npc = alife_object(npc_id) if (not se_npc) then return end -- Collect ammo list local t = {} for id in alife():get_children(se_npc) do local se_item = alife_object(id) if se_item and IsAmmo(nil,se_item:clsid())then local sec = se_item:section_name() t[sec] = t[sec] or {} t[sec][se_item.id] = true end end -- Release all extra ammo, keep one box per section local cnt = 0 for sec,v in pairs(t) do if size_table(v) > 1 then --printf("NPC [%s] has %s [%s]", se_npc:name(), size_table(v), sec) local ignore_once = false for id,_ in pairs(v) do if (not ignore_once) then ignore_once = true else cnt = cnt + 1 alife_release_id(id) end end end end --[[ if cnt > 1 then printf("~Release (%s) ammo box from NPC [%s]", cnt, se_npc:name()) end --]] end ------------------------------------------------------------------- GUI = nil -- instance, don't touch local aw_cooldown = 0 function start_ammo_wheel() local wpn = db.actor:active_item() if wpn and IsWeapon(wpn) and (not IsItem("fake_ammo_wpn",wpn:section())) then hide_hud_inventory() if (not GUI) then GUI = UIWheelAmmo() end if (GUI) and (not GUI:IsShown()) then GUI:ShowDialog(true) GUI:Reset(wpn) aw_cooldown = time_global() Register_UI("UIWheelAmmo","item_weapon") end end end class "UIWheelAmmo" (CUIScriptWnd) function UIWheelAmmo:__init() super() self.object = nil self.id = nil self.section = nil self.ammo_type = nil self.ammo_list = {} self.ammo_max = 12 self.show_verybad = (not _NO_DAMAGED_AMMO) self.ammo_inv = {} self.avail = {} self.key = {} for i=1,9 do nums_dik[ DIK_keys["DIK_" .. i] ] = i nums_dik[ DIK_keys["DIK_NUMPAD" .. i] ] = i end self:InitControls() self:InitCallBacks() end function UIWheelAmmo:__finalize() end function UIWheelAmmo:InitControls() self:SetWndRect (Frect():set(0,0,1024,768)) self:SetAutoDelete(true) self:AllowMovement(true) self.xml = CScriptXmlInit() local xml = self.xml xml:ParseFile ("ui_wheel_ammo.xml") self.dialog = xml:InitStatic("wheel", self) self.background = xml:InitStatic("wheel:background", self.dialog) self.extended = xml:InitStatic("wheel:extended", self.dialog) local box_type = self.show_verybad and ":all" or ":alt" self.box_r = xml:InitStatic("wheel:result", self.dialog) self.box_icon_tmp_r = xml:InitStatic("ammo:icon", self.box_r) self.box = {} self.box_icon = {} self.box_icon_r = {} self.box_icon_tmp = {} self.box_num = {} self.box_txt = {} self.box_txt_r = {} self.box_btn = {} self.box_hl_1 = {} self.box_hl_2 = {} for i=1,self.ammo_max do self.box[i] = xml:InitStatic("wheel" .. box_type .. ":box_" .. i, self.dialog) self.box_hl_1[i] = xml:InitStatic("ammo:highlight", self.box[i]) self.box_hl_2[i] = xml:InitStatic("ammo:highlight", self.box[i]) self.box_icon[i] = xml:InitStatic("ammo:icon", self.box[i]) self.box_icon_tmp[i] = xml:InitStatic("ammo:icon", self.box[i]) self.box_num[i] = xml:InitTextWnd("ammo:num", self.box[i]) self.box_txt[i] = xml:InitTextWnd("ammo:text", self.box[i]) self.box_btn[i] = xml:Init3tButton("ammo:btn", self.box[i]) self:Register(self.box_btn[i],"btn_" .. i) self.box_icon_r[i] = xml:InitStatic("ammo:icon", self.box_r) self.box_txt_r[i] = xml:InitTextWnd("ammo:text_r", self.box_r) end end function UIWheelAmmo:InitCallBacks() for i=1,self.ammo_max do local _wrapper = function(handler) -- we need wrapper in order to pass ctrl to method self:OnAmmo(i) end self:AddCallback("btn_" .. i, ui_events.BUTTON_CLICKED, _wrapper, self) end end function UIWheelAmmo:Update() CUIScriptWnd.Update(self) for i=1,self.ammo_max do if self.box_btn[i] then if self.box_btn[i]:IsCursorOverWindow() then self.box_icon_r[i]:Show(true) self.box_txt_r[i]:Show(true) else self.box_icon_r[i]:Show(false) self.box_txt_r[i]:Show(false) end end end end function get_grenades(section) local s = ini_sys:r_string_ex(section, "grenade_class") local x = s and str_explode(s,",") return x end function UIWheelAmmo:Reset(obj) self.object = obj self.id = obj:id() self.section = obj:section() self.ammo_type = obj:get_ammo_type() self.grenade_mode = obj:weapon_in_grenade_mode() and true or false -- Collect weapon's ammo list if (not cache_ammo[self.id]) then cache_ammo[self.id] = utils_item.get_ammo(self.section, self.id) -- Cut anything with more than 12 ammo types if (#cache_ammo[self.id] > self.ammo_max) then for i=self.ammo_max, #cache_ammo[self.id] do cache_ammo[self.id][i] = nil end end end self.ammo_list = self.grenade_mode and get_grenades(self.section) or cache_ammo[self.id] if not self.ammo_list then printf("ERROR: could not find ammo list for [%s] - grenade mode: %s", self.section, self.grenade_mode) self:Close() end -- Collect all ammo in inventory empty_table(self.ammo_inv) local function itr(temp, itm) local section = itm:section() if IsItem("ammo",section) or IsItem("grenade_ammo",section) then self.ammo_inv[section] = (self.ammo_inv[section] or 0) + itm:ammo_get_count() end end db.actor:iterate_inventory(itr, nil) -- Reset XML elements self.extended:Show((#self.ammo_list > 9) and (self.ammo_list[10] ~= "ammo_12x70_buck_self")) --self.box_r:Show(false) local cnt = 0 empty_table(self.key) for i=1,self.ammo_max do local section = self.ammo_list[i] local found_verybad = section and string.find(section,"verybad") and true or false if section and (section ~= "ammo_12x70_buck_self") and ( self.show_verybad or ( (not self.show_verybad) and (not found_verybad) ) ) then -- Show box and highlighted ammo local is_curr_ammo = (self.ammo_type == (i - 1)) self.box[i]:Show(true) self.box_hl_1[i]:Show(is_curr_ammo) self.box_hl_2[i]:Show(is_curr_ammo) self.avail[i] = self.ammo_inv[section] and (self.ammo_inv[section] > 0) and true or false utils_xml.set_icon(section, (not self.avail[i]), self.box_icon[i], self.box_icon_tmp[i]) utils_xml.set_icon(section, nil, self.box_icon_tmp_r, self.box_icon_r[i]) cnt = cnt + 1 self.key[cnt] = i if self.avail[i] and i <= 9 then self.box_num[i]:SetText(cnt) else self.box_num[i]:SetText("") end -- Show ammo count self.box_txt[i]:SetText("x" .. (self.avail[i] and self.ammo_inv[section] or 0)) self.box_txt_r[i]:SetText( ui_item.get_sec_name(section) ) else self.avail[i] = false self.box[i]:Show(false) end end end function UIWheelAmmo:SwitchNextAmmo() local wpn = db.actor:active_item() if wpn and (wpn:section() == self.section) then local new_type local ammo_type = wpn:get_ammo_type() -- Search for available next ammo types for i=(ammo_type + 2),self.ammo_max do -- +2 because we need next type (+1 is the current type in ammo table) if self.avail[i] then new_type = i break end end -- Search for available earlier ammo types if (not new_type) then for i=1,ammo_type do if self.avail[i] then new_type = i break end end end if new_type then wpn:unload_magazine(true) wpn:set_ammo_type(new_type - 1) -- ammo type starts from 0 db.actor:reload_weapon() end end self:Close() end function UIWheelAmmo:OnAmmo(n) local wpn = db.actor:active_item() if wpn and (wpn:section() == self.section) and self.avail[n] then local ammo_type = wpn:get_ammo_type() if (ammo_type ~= n - 1) then wpn:unload_magazine(true) wpn:set_ammo_type(n - 1) -- ammo type starts from 0 db.actor:reload_weapon() end end self:Close() end function UIWheelAmmo:OnKeyboard(dik, keyboard_action) local res = CUIScriptWnd.OnKeyboard(self,dik,keyboard_action) if (res == false) then if keyboard_action == ui_events.WINDOW_KEY_RELEASED then if (time_global() < aw_cooldown + 100) then return end local bind = dik_to_bind(dik) local num = nums_dik[dik] if (bind == key_bindings.kWPN_NEXT) then ui_delay = time_global() + ui_delay_const self:SwitchNextAmmo() elseif num and self.key[num] then self:OnAmmo( self.key[num] ) elseif (bind == key_bindings.kQUIT or bind == key_bindings.kUSE) then self:Close() end end end return res end function UIWheelAmmo:Close() if self:IsShown() then self:HideDialog() self:Show(false) Unregister_UI("UIWheelAmmo") end end ------------------------------- -- OVERHEAT ------------------------------- can_overheat = true local overheat_threshold = 100 local time_quant local decrease_quant local max_overheat = 150 local overheat = 0 local smoke local last_wpn_id function update_overheat() if overheat < overheat_threshold then decrease_quant = 0.2 else decrease_quant = 0.1 end local wpn = db.actor:active_item() if not wpn then return end if (string.match(tostring(wpn:section()),"knife") or string.match(tostring(wpn:section()),"axe")) then return end if IsWeapon(wpn) then -- reset overheat value on weapon change if not (last_wpn_id) then last_wpn_id = wpn:id() end if (last_wpn_id ~= wpn:id()) then overheat = 0 last_wpn_id = wpn:id() end if not (can_overheat) then return end local rpm = ui_wpn_params.GetRPM(wpn:section()) -- Grab packet data local se_wpn = alife_object(wpn:id()) local data = utils_stpk.get_weapon_data(se_wpn) if not data then return end --printf("RPM: "..rpm) time_quant = rpm/100 -- Check if weapon firing if (data.weapon_state == 5) then -- increase overheat quantity over time overheat = overheat + time_quant <= max_overheat and overheat + time_quant or max_overheat else -- Stop playing particle if value less then threshold if (overheat < overheat_threshold) then if (smoke and smoke:playing()) then smoke:stop() end end end --printf("-heat: "..overheat.."/"..overheat_threshold) -- if overheating greater then threshold if (overheat >= overheat_threshold) then -- create particle if not exist if not (smoke) then smoke = particles_object("industrial_particles\\weapon_smoke") end -- play at bone position if not (smoke:playing()) then smoke:play_at_pos( wpn:bone_position("wpn_body") ) end -- move to firepoint local hud = utils_data.read_from_ini(nil,wpn:section(),"hud","string",nil) local fire_bone = utils_data.read_from_ini(nil,hud,"fire_bone","string",nil) or "wpn_body" local offset = utils_data.read_from_ini(nil,hud,"fire_point","string",nil) or VEC_ZERO offset = offset and utils_data.string_to_vector(offset) smoke:move_to( wpn:bone_position(fire_bone), offset ) end -- decrease quantity over time overheat = overheat - decrease_quant >= 0 and overheat - decrease_quant or 0 end end ------------------------------- -- CALLBACKS ------------------------------- local function actor_on_item_use(item) -- Attachments if (scopes_table[item:section()]) then attach_scope(item,get_weapon_slot()) end -- Multi-Tool (Compatibility) if (item:section() == "addons_box") then detach_scope(get_weapon_slot()) end end local function on_item_drag_dropped(obj_1, obj_2, slot_from, slot_to) -- Check capability if not (slot_from == EDDListType.iActorBag and (slot_to == EDDListType.iActorBag or slot_to == EDDListType.iActorSlot)) then return end local parent = obj_2:parent() if not (IsWeapon(obj_2) and parent and parent:id() == AC_ID) then return end local sec_1 = obj_1:section() local sec_2 = obj_2:section() -- Inject ammo if IsItem("ammo",sec_1) then --ammo_injection(obj_1, obj_2, sec_1, sec_2) -- Attach scope elseif (check_scope(sec_1, sec_2)) then attach_scope(obj_1, obj_2) end end local function on_key_release(key) local bind = dik_to_bind(key) -- Ammo wheel if (bind == key_bindings.kWPN_NEXT) and (time_global() > ui_delay) then start_ammo_wheel() -- Toggle silencer elseif (bind == key_bindings.kCUSTOM13) then test_silencer() -- Unload all weapons elseif (bind == key_bindings.kCUSTOM15) then unload_all_weapons() end end local function actor_on_update() update_overheat() end local function move(npc_id, obj, mode, bag_from) if mode == "loot" and bag_from == EDDListType.iActorBag and IsAmmo(obj) then CreateTimeEvent("box", "box_agg", 0, function(ammo_id, box_id) local box = get_object_by_id(box_id) local ammo = get_object_by_id(ammo_id) if box and ammo then ammo_aggregation(ammo, box) end return true end, obj:id(), npc_id) end end function on_game_start() RegisterScriptCallback("ActorMenu_on_item_drag_drop",on_item_drag_dropped) RegisterScriptCallback("on_key_release",on_key_release) RegisterScriptCallback("actor_on_update",actor_on_update) RegisterScriptCallback("ActorMenu_on_item_after_move", move) if (ini_sys:section_exist("addons_table")) then --[[ local snd_targets = get_console_cmd(2,"snd_targets") if (snd_targets < 32) then exec_console_cmd("snd_targets 32") exec_console_cmd("snd_restart") end --]] RegisterScriptCallback("actor_on_item_use", actor_on_item_use) end end